<script>
  // @ts-nocheck

  import * as d3 from "d3";
  import { voronoiTreemap } from "d3-voronoi-treemap";
  import * as _ from "lodash-es";
  import seedrandom from "seedrandom";

  import DataPop from "../components/DataPop.svelte";
  import settingPng from "../assets/option.png";
  import refreshPng from "../assets/refresh.png";

  const _2PI = 2 * Math.PI;
  const _voronoiTreemap = voronoiTreemap();
  const fontScale = d3.scaleLinear();

  let hierarchy, circlingPolygon, rootData, zoom, svg;
  let prng;
  let svgWidth = window.innerWidth - 20,
    svgHeight = window.innerHeight - 20,
    margin = { top: 10, right: 10, bottom: 10, left: 10 },
    height = svgHeight - margin.top - margin.bottom,
    width = svgWidth - margin.left - margin.right,
    halfWidth = width / 2,
    halfHeight = height / 2,
    treemapRadius = 0.45 * Math.min(window.innerHeight, window.innerWidth),
    treemapCenter = [halfWidth, halfHeight + 5];
  let drawConfig = {
    stroke: {
      l0Width: "4",
      l0Color: "#fff",
      l1Width: "3",
      l1Color: "#fff",
      l2Width: "3",
      l2Color: "#fff",
    },
    dataFlag: "0",
  };
  let transform = `translate(${margin.left},${margin.top})`;
  let popoverPos = [-1000, -1000];
  let popoverData = [];
  let popoverTitle = "";
  circlingPolygon = computeCirclingPolygon(treemapRadius);
  fontScale.domain([1000, 200000]).range([4, 14]).clamp(true);

  export async function draw(config) {
    drawConfig = config.detail;
    if (!rootData) {
      rootData = await d3.json("/dv1/carData.json");

      zoom = d3.zoom();
      zoom.scaleExtent([0.1, 10]);
      zoom.on("zoom", (e) => {
        console.log(e);
        transform = `translate(${margin.left + e.transform.x},${
          margin.top + e.transform.y
        }) scale(${e.transform.k})`;
      });
      svg = d3.select("#chartSvg");
      svg.call(zoom).call(zoom.transform, d3.zoomIdentity.scale(1));
    }
    let displayData;
    if (drawConfig.dataFlag !== "0") {
      // rootData
      // console.log(rootData);
      displayData = {
        ...rootData,
        children: rootData.children.map((fc) => {
          if (!fc.children) {
            return fc;
          }
          return {
            ...fc,
            children: fc.children.map((bd) => {
              if (!bd.children) {
                return bd;
              }
              return {
                ...bd,
                children: bd.children.map((se) => {
                  if (!se.data || se.data.length <= 1) {
                    return se;
                  }
                  return {
                    ...se,
                    data: [se.data[Number(drawConfig.dataFlag)]],
                  };
                }),
              };
            }),
          };
        }),
      };
    }

    if (drawConfig.prng) {
      prng = seedrandom(drawConfig.prng);
      _voronoiTreemap.prng(prng);
    }
    hierarchy = d3.hierarchy(displayData || rootData).sum(function (d) {
      return d.total;
    });
    // @ts-ignore
    _voronoiTreemap.clip(circlingPolygon)(hierarchy);
  }
  function initPos() {
    transform = `translate(${margin.left},${margin.top})`;
  }
  function computeCirclingPolygon(radius) {
    var points = 120,
      increment = _2PI / points,
      circlingPolygon = [];

    for (var a = 0, i = 0; i < points; i++, a += increment) {
      circlingPolygon.push([
        radius + radius * Math.cos(a),
        radius + radius * Math.sin(a),
      ]);
    }

    return circlingPolygon;
  }

  function getCellColor(d) {
    let bg = d.data.color || d.parent.data.color;
    if (bg) {
      return `rgb(${bg[0]},${bg[1]},${bg[2]})`;
    }
    return "transparent";
  }
  function getLabelColor(d) {
    let bg = d.data.color || d.parent.data.color;
    if (bg) {
      // @ts-ignore
      let color = d3.color(`rgb(${bg})`).formatHsl();
      if (Number(color.split(",")[2].slice(0, -2)) < 50) {
        return "#fff";
      }
    }
    return "#333";
  }
  const onFocusCell = _.debounce(function (e, cell) {
    // console.log(cell);
    // e.preventDefault();
    // console.log("focus");
    let offsetX = 0,
      offsetY = 0;
    if (e.offsetY + 500 > svgHeight) {
      offsetY = svgHeight - 500;
    }
    popoverPos = [offsetX || e.offsetX, offsetY || e.offsetY];

    popoverData = cell.data.data || [cell.data.total];
    popoverTitle = `${cell.parent.data.name}-${cell.data.name}`;
    if (drawConfig.dataFlag && drawConfig.dataFlag !== "0") {
      popoverTitle = [popoverTitle, `${drawConfig.dataFlag}月`].join("-");
    }
  }, 300);
  const onBlurG = _.debounce(function (e) {
    // e.preventDefault();
    // console.log("bl");
    // alert(e.target.innerHTML);
    popoverPos = [-1000, -1000];
    popoverData = [];
    popoverTitle = "";
  }, 300);
</script>

<div class="chart-main drawer-content">
  <svg id="chartSvg" width={svgWidth} height={svgHeight}>
    <g {transform}>
      <g
        class="treemap-container"
        transform={`translate(${treemapCenter})`}
        on:mouseleave|self={onBlurG}
      >
        {#if circlingPolygon}
          <path
            class="cn"
            transform={`translate(${[-treemapRadius, -treemapRadius]})`}
            stroke={drawConfig.stroke.l0Color}
            stroke-width={drawConfig.stroke.l0Width}
            fill-opacity="0"
            d={`M ${circlingPolygon.join(",")} Z`}
          />
        {/if}
        {#if hierarchy}
          <g
            class="borders"
            transform={`translate(${[-treemapRadius, -treemapRadius]})`}
          >
            {#each hierarchy.children as border}
              <path
                d={`M ${border.polygon.join(",")} Z`}
                stroke={drawConfig.stroke.l1Color}
                stroke-width={drawConfig.stroke.l1Width}
                fill="transparent"
              />
            {/each}
          </g>
          <g
            class="cells"
            transform={`translate(${[-treemapRadius, -treemapRadius]})`}
          >
            {#each hierarchy.leaves() as cell}
              <path
                class="cell"
                d={`M ${cell.polygon.join(",")} Z`}
                stroke={drawConfig.stroke.l2Color}
                stroke-width={drawConfig.stroke.l2Width}
                fill-opacity="0.65"
                fill={getCellColor(cell)}
                on:mouseenter={(e) => onFocusCell(e, cell)}
              />
            {/each}
          </g>
          <g
            class="labels"
            transform={`translate(${[-treemapRadius, -treemapRadius]})`}
          >
            {#each hierarchy.leaves() as label}
              <g
                class="label"
                transform={`translate(${[
                  label.polygon.site.x,
                  label.polygon.site.y,
                ]})`}
                font-size={fontScale(label.data.total)}
                fill={getLabelColor(label)}
              >
                <text text-anchor="middle"
                  >{label.data.total < 10000 ? "" : label.data.name}</text
                >
              </g>
            {/each}
          </g>
        {/if}
      </g>
    </g>
  </svg>
  <DataPop rect={popoverPos} title={popoverTitle} data={popoverData} />
  <label
    for="my-drawer"
    class="setting-btn"
    style={`background-image:url(${settingPng})`}
  />
  <div
    class="refresh-btn"
    on:click={initPos}
    style={`background-image:url(${refreshPng})`}
  />
</div>

<style>
  .cn {
    background-color: transparent;
  }
  .cell {
    cursor: pointer;
  }
  .cell:hover {
    fill-opacity: 0.45;
  }
  .label {
    user-select: none;
    font-weight: 600;
  }
  .setting-btn {
    width: 32px;
    height: 32px;
    background-size: 100%;
    background-repeat: no-repeat;
    position: fixed;
    right: 20px;
    top: 20px;
    cursor: pointer;
  }
  .refresh-btn {
    width: 32px;
    height: 32px;
    background-size: 100%;
    background-repeat: no-repeat;
    position: fixed;
    right: 72px;
    top: 20px;
    cursor: pointer;
  }
</style>
